#include "rs485_private_device.h"
#include "print_rtt.h"
#include "string.h"
#include "stdio.h"
#include "FreeRTOS.h"
#include "task.h"
int rs485_private_device_st_register(
    struct rs485_private_device_st *rs485_p_device,
    struct rs485_rtx_st *rx_st,
    struct rs485_rtx_st *rx_f_st,
    struct rs485_rtx_st *tx,
    struct rs485_hw *hw_st,
    void (*microsecond_delay)(unsigned int microseconds),
    void (*watchdog_feed)(void))
{
    rs485_p_device->rx = rx_st;
    rs485_p_device->rx_finished = rx_f_st;
    rs485_p_device->tx = tx;
    rs485_p_device->hw_st = hw_st;
    memset(rs485_p_device->rx, 0, sizeof(struct rs485_rtx_st));
    memset(rs485_p_device->rx_finished, 0, sizeof(struct rs485_rtx_st));
    memset(rs485_p_device->tx, 0, sizeof(struct rs485_rtx_st));
    // rs485_p_device->running_status = STANDBY;
    rs485_p_device->microsecond_delay = microsecond_delay;
    rs485_p_device->watchdog_feed = watchdog_feed;
    rs485_p_device->wait_send_data_finished = wait_send_data_finished;
    // rs485_p_device->enable_uart = enable_st_uart;
    rs485_p_device->start_to_send_out = start_to_send_out;
    rs485_p_device->check_receive_interrupt = check_receive_interrupt;
    rs485_p_device->add_one_byte_to_received_buffer = add_one_byte_to_received_buffer;
    rs485_p_device->send_out_frame_process = send_out_frame_process;
    rs485_p_device->fetch_one_need_send_byte = fetch_one_need_send_byte;
    rs485_p_device->check_receive_timeout_timer_interrupt = check_receive_timeout_timer_interrupt;
    rs485_p_device->receive_timeout_proccess = receive_timeout_proccess;
    return PR_EOK;
}
int rs485_private_send_out_order_and_fetch_response(struct rs485_private_device_st *rs485_p_device,
                                                    uint16_t pos,
                                                    uint8_t *send_buffer,
                                                    uint16_t size,
                                                    uint8_t *response_buffer,
                                                    uint16_t *response_szie,
                                                    uint16_t response_timeout)
{
    uint16_t tmp_size;
    uint16_t currnt_wait_timer_count, wait_timer_count = response_timeout / 10;
    tmp_size = rs485_private_read(rs485_p_device, pos, response_buffer, *response_szie);
    tmp_size = rs485_private_write(rs485_p_device, pos, send_buffer, size);
    if (tmp_size != size)
    {
        LOG_ERROR("send out error!\r\n");
        return -1;
    }
    currnt_wait_timer_count = 0;
    while (1)
    {
        tmp_size = rs485_private_read(rs485_p_device, pos, response_buffer, 300);
        if (tmp_size != 0)
        {
            *response_szie = tmp_size;
            return 0;
        }
        if (currnt_wait_timer_count >= wait_timer_count)
        {
            return -1;
        }
        vTaskDelay(10);
        currnt_wait_timer_count++;
    }
}
uint16_t rs485_private_write(struct rs485_private_device_st *rs485_p_device, uint16_t pos, const void *buffer, uint16_t size)
{
    if (size > 300)
    {
        return 0;
    }
    if (0 == rs485_p_device->wait_send_data_finished(rs485_p_device))
    {
        return 0;
    }
    rs485_p_device->start_to_send_out(rs485_p_device, (uint8_t *)buffer, size);
    // if (0 == rs485_p_device->wait_send_data_finished(rs485_p_device))
    // {int
    //     return 0;
    // }
    return size;
}
uint16_t rs485_private_read(struct rs485_private_device_st *rs485_p_device, uint16_t pos, void *buffer, uint16_t size)
{
    uint32_t return_value_buffer_size;
    if (rs485_p_device->rx_finished->status == 1)
    {
        memcpy(buffer, rs485_p_device->rx_finished->buffer, rs485_p_device->rx_finished->save_index);
        memset(rs485_p_device->rx_finished->buffer, 0, rs485_p_device->rx_finished->save_index);
        return_value_buffer_size = rs485_p_device->rx_finished->save_index;
        rs485_p_device->rx_finished->status = 0;
    }
    else
    {
        return_value_buffer_size = 0;
    }
    return return_value_buffer_size;
}

void rs485_private_rtx_isr(struct rs485_private_device_st *rs485_p_device)
{
    uint8_t byte;
    if (rs485_p_device->check_receive_interrupt(rs485_p_device, &byte))
    {
        rs485_p_device->add_one_byte_to_received_buffer(rs485_p_device, byte);
    }
    rs485_p_device->send_out_frame_process(rs485_p_device);
}
void rs485_private_rx_tim_isr(struct rs485_private_device_st *rs485_p_device)
{

    if (rs485_p_device->check_receive_timeout_timer_interrupt(rs485_p_device))
    {
        //        __breakpoint(0);
        rs485_p_device->receive_timeout_proccess(rs485_p_device);
    }
}

int wait_send_data_finished(struct rs485_private_device_st *rs485_p_device)
{
    int i = 0;
    int timesout = rs485_p_device->tx->save_index * 5;
    if (rs485_p_device->tx->status == 0)
    {
        return 1;
    }
    while (1)
    {
        i++;
        rs485_p_device->microsecond_delay(1);
        rs485_p_device->watchdog_feed();
        // seconds_delay(1);
        // rt_thread_delay(RT_TICK_PER_SECOND / 100);
        if (i >= timesout)
        {
            return 0;
        }
        if (rs485_p_device->tx->status == 0)
        {
            break;
        }
    }
    return 1;
}

// static void enable_st_uart(struct rs485_private_device_st* rs485_p_device)
//{
//     // hw_st->enable_uart();
//     // hw_st->set_oe_to_receive();
// }

static void start_to_send_out(struct rs485_private_device_st *rs485_p_device, uint8_t *buffer, uint16_t size)
{
    struct rs485_hw *hw_st = rs485_p_device->hw_st;
    hw_st->set_oe_to_send();
    rs485_p_device->running_status = SENDING;
    memcpy(rs485_p_device->tx->buffer, buffer, size);
    rs485_p_device->tx->save_index = size;
    rs485_p_device->tx->read_index = 0;
    rs485_p_device->tx->status = 1;
    hw_st->start_to_send();
}

uint8_t check_receive_interrupt(struct rs485_private_device_st *rs485_p_device, uint8_t *buf)
{
    struct rs485_hw *hw = rs485_p_device->hw_st;
    return hw->check_receive_interrupt_registers_data(buf);
}
void add_one_byte_to_received_buffer(struct rs485_private_device_st *rs485_p_device, uint8_t byte)
{
    struct rs485_hw *hw = rs485_p_device->hw_st;
    rs485_p_device->running_status = RECEIVEING;
    hw->start_receive_timeout_timer();
    switch (rs485_p_device->rx->status)
    {
    case 0:
        rs485_p_device->rx->save_index = 0;
        rs485_p_device->rx->buffer[rs485_p_device->rx->save_index] = byte;
        rs485_p_device->rx->save_index++;
        rs485_p_device->rx->status = 1;
        break;
    case 1:
        if (rs485_p_device->rx->save_index >= 300)
        {
            rs485_p_device->rx->status = 0;
            break;
        }
        rs485_p_device->rx->buffer[rs485_p_device->rx->save_index] = byte;
        rs485_p_device->rx->save_index++;
        break;
    default:
        rs485_p_device->rx->save_index = 0;
        rs485_p_device->rx->buffer[rs485_p_device->rx->save_index] = byte;
        rs485_p_device->rx->save_index++;
        rs485_p_device->rx->status = 1;
        break;
    }
}

void send_out_frame_process(struct rs485_private_device_st *rs485_p_device)
{
    uint8_t byte;
    struct rs485_hw *hw = rs485_p_device->hw_st;
    if (hw->check_txe_empty_interrupt())
    {
        if (rs485_p_device->fetch_one_need_send_byte(rs485_p_device, &byte))
        {
            hw->send_out_one_byte(byte);
            hw->enable_txe_empty_interrupt();
        }
        else
        {
            hw->enable_wait_tc_empty_interrupt();
        }
    }
    if (hw->check_tc_empty_interrupt())
    {
        hw->set_oe_to_receive();
        rs485_p_device->tx->status = 0;
        rs485_p_device->running_status = STANDBY;
    }
}
uint8_t fetch_one_need_send_byte(struct rs485_private_device_st *rs485_p, uint8_t *byte)
{
    if (rs485_p->tx->read_index > (rs485_p->tx->save_index - 1))
    {
        return 0;
    }
    else
    {
        *byte = rs485_p->tx->buffer[rs485_p->tx->read_index];
        rs485_p->tx->read_index++;
        return 1;
    }
}

uint8_t check_receive_timeout_timer_interrupt(struct rs485_private_device_st *rs485_p_device)
{
    struct rs485_hw *hw = rs485_p_device->hw_st;
    return hw->check_receive_timeout_timer_interrput();
}
void receive_timeout_proccess(struct rs485_private_device_st *rs485_p_device)
{
    struct rs485_hw *hw = rs485_p_device->hw_st;
    if (rs485_p_device->running_status == SENDING)
    {
        hw->set_oe_to_receive();
        rs485_p_device->tx->status = 0;
    }
    else
    {
        if (rs485_p_device->rx->status == 1)
        {
            memcpy(rs485_p_device->rx_finished->buffer, rs485_p_device->rx->buffer, rs485_p_device->rx->save_index);
            rs485_p_device->rx_finished->save_index = rs485_p_device->rx->save_index;
            rs485_p_device->rx_finished->status = rs485_p_device->rx->status;
            rs485_p_device->rx->status = 0;
        }
    }
    rs485_p_device->running_status = STANDBY;
}
